package com.koron.util.secret;

import com.koron.util.Constant;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.swan.bean.MessageBean;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Map;


/**
 * 请求加解密，判断是否合法
 */
@Component
public class SecretReqUtil {

    private static Logger log = LogManager.getLogger(SecretReqUtil.class);
    
    private static String mdAppId ;// 应用id
    
    @Value("${md.identify.appId}")
    public void setMdAppId(String mdAppId) {
        this.mdAppId = mdAppId;
    }
    
    private static Map<String,String> KEY;

    @Value("#{${secretKey}}")
	public void setKEY(Map<String, String> kEY) {
    	SecretReqUtil.KEY = kEY;
	}

    public static MessageBean decodeResult(RequestBean req){
        if (req == null) {
            return MessageBean.create(Constant.REQUEST_IS_NULL, "请求不能为空",Object.class);
        }
        // 校验身份
        if (StringUtils.isBlank(req.getSecret())) {
            return MessageBean.create(Constant.REQUEST_SECRET_NULL, "加密认证不能为空",Object.class);
        } else {
            try {
                String encrypt = req.getSecret();
                req.setSecret(null);
                String md5 = DigestUtils.md5Hex(req.toJson());
                String decode = decode3Des(KEY.get(req.getAppid()), encrypt);
                String time = decode.substring(0, decode.indexOf("_"));
                decode = decode.substring(decode.indexOf("_") + 1);
                if (System.currentTimeMillis() - Long.parseLong(time) > 500000) {// 超时3秒
                    return MessageBean.create(Constant.REQUEST_OUTTIME, "请校准服务器时间",Object.class);
                } else {
                    if (!decode.equals(md5)) {
                        return MessageBean.create(Constant.SECRET_IS_DIFFERENCE, "指令加密信息不一致，请确认加密方式是否合法",Object.class);
                    }
                }
            } catch (Exception e) {
                log.error("请求信息解密錯誤", e);
                return MessageBean.create(Constant.REQUEST_DECODE_ERROR, "请求信息解密錯誤",Object.class);
            }
        }
        return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "success", Object.class);
    }

    /**
     * 3DES解密
     *
     * @param key
     *            加密密钥，长度为24字节
     * @param desStr
     *            解密后的字符串
     * @return
     *
     * 		lee on 2017-08-09 10:52:54
     */
    private static String decode3Des(String key, String desStr) throws Exception {
        if (key.getBytes().length < 24) {
            throw new Exception("密码长度不能小于24个字符");
        }
        byte[] src = Base64.getDecoder().decode(desStr);
        // 生成密钥
        SecretKey deskey = new SecretKeySpec(key.getBytes(), "DESede");
        // 解密
        Cipher c1 = Cipher.getInstance("DESede");
        c1.init(Cipher.DECRYPT_MODE, deskey);
        String pwd = new String(c1.doFinal(src));
        return pwd;
    }

    public static String sendToGatWay(RequestBean<T> bean) throws Exception {
    	if(StringUtils.isBlank(bean.getAppid()))bean.setAppid(mdAppId);
        String encrypt = getMd5Hex(bean);
        bean.setSecret(encrypt);
        String url = bean.getUrl();
        String param = bean.toJson();
        return HttpUtils.sendPost(url, param, "");
    }

    /**
     * 3Des加密
     *
     * @param srcStr
     * @return
     * @throws Exception
     */
    private static String encode3Des(String key,String srcStr) throws Exception {
        if (key.getBytes().length < 24) {
            throw new Exception("密码长度不能小于24个字符");
        }
        byte[] src = srcStr.getBytes();
        // 生成密钥
        SecretKey deskey = new SecretKeySpec(key.getBytes(), "DESede");
        // 加密
        Cipher c1 = Cipher.getInstance("DESede");
        c1.init(Cipher.ENCRYPT_MODE, deskey);

        String pwd = Base64.getEncoder().encodeToString(c1.doFinal(src));
        return pwd;
    }

    private static String getMd5Hex(RequestBean bean) throws Exception {
        return encode3Des(KEY.get(bean.getAppid()),System.currentTimeMillis() + "_" + DigestUtils.md5Hex(bean.toJson()));
    }

	public static String sendToJc(RequestBean<T> bean,String orderType) throws Exception {
		if(StringUtils.isBlank(bean.getAppid()))bean.setAppid("004");
        String encrypt =encode3Des("123456789012345678901234",System.currentTimeMillis() + "_" + DigestUtils.md5Hex(bean.toJson()));
        bean.setSecret(encrypt);
        String url = bean.getUrl();
        String param = bean.toJson();
        log.info("调用集抄处理自动阀控 -请求参数 url:{} param:{} orderType:{}",url,param,orderType);
        return HttpUtils.sendPost(url, param, orderType);
	}
}
